﻿using ProjectFootball.MVC.Areas.CompetitionArea.Models;
using ProjectFootball.MVC.Foundation;
using ProjectFootball.MVC.Foundation.ResourceLibrary;
using ProjectFootball.MVC.Models.EntityFramework.Entities;
using ProjectFootball.MVC.Models.RepositoryProviders;
using System;
using System.Linq;
using System.Security.Principal;
using System.Web.Mvc;

namespace ProjectFootball.MVC.Areas.CompetitionArea.Controllers
{
    [Authorize]
    public class EditorController : BaseController
    {
        #region Constructor
        public EditorController(IRepositoryProvider provider)
            :base(provider)
        {
        }
        #endregion

        #region /CompetitionArea/Editor
        public ActionResult Index(Guid id)
        {
            var competition = Provider.CompetitionRepository.SearchByPrimaryKey(id);

            if (competition == null)
                return RedirectHome;

            var competitionViewModel = competition.GetCompetitionViewModel(User, SearchType.Details);
            competitionViewModel.CompetitionDataModel = competition.GetDataModel();
            competitionViewModel.CompetitionDataModel.EditorDbType = competition.GetEditorDbTypeForEdit(User);

            return View(competitionViewModel);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(CompetitionDataModel competitionDataModel)
        {
            var competition = Provider.CompetitionRepository.SearchByPrimaryKey(competitionDataModel.CompetitionGuid);
            var competitionViewModel = competition.GetCompetitionViewModel(User, SearchType.Details);
            competitionViewModel.CompetitionDataModel = competitionDataModel;
            
            if (!ModelState.IsValid)
                return View(competitionViewModel);

            if (competition.CanEdit(User))
            {
                competition.Edit(competitionDataModel, User);
                SetEditDbType(competition);
            }
            else
            {
                competition = competitionDataModel.CreateNew(User, CreateType.Unapproved);
                Provider.CompetitionRepository.Add(competition);
                SetCreateDbType(competition);
            }

            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = competition.Pk });
        }
        #endregion

        #region /CompetitionArea/Editor/CreateNew
        public ActionResult CreateNew()
        {
            var competitionViewModel = new CompetitionViewModel()
            {
                CompetitionDataModel = new CompetitionDataModel()
                {
                    EditorDbType = User.IsApprover() ? DbType.CreatedPublic : DbType.CreatedPrivate
                }
            };

            return View("Index", competitionViewModel); 
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult CreateNew(CompetitionDataModel competitionDataModel)
        {
            if (!ModelState.IsValid)
                return View("Index", new CompetitionViewModel() { CompetitionDataModel = competitionDataModel });

            var createType = User.IsApprover() ? CreateType.Public : CreateType.Private;

            var competition = competitionDataModel.CreateNew(User, createType);

            if (competition.CountryGuid != null)
                competition.Country = Provider.CountryRepository.SearchByPrimaryKey((Guid)competition.CountryGuid);

            Provider.CompetitionRepository.Add(competition);

            Provider.SaveChanges();

            SetCreateDbType(competition);

            return RedirectToAction("Index", "Details", new { id = competition.Pk });
        }
        #endregion

        #region /CompetitionArea/Editor/Delete
        public ActionResult Delete(Guid id)
        {
            var competition = Provider.CompetitionRepository.SearchByPrimaryKey(id);

            if (competition == null || !competition.CanDelete(User))
                return RedirectHome;

            competition.MarkForDeletion();
            SetDbType(DbType.MarkedForDeletion);
            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = competition.Pk });
        }
        #endregion

        #region /CompetitionArea/Editor/RecordForApproval
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult RecordForApproval(Guid id)
        {
            var competition = Provider.CompetitionRepository.SearchByPrimaryKey(id);

            if (competition == null)
                return RedirectHome;

            var competitions = Provider.CompetitionRepository.Where(c => c.ApprovalGuid == competition.ApprovalGuid);

            return View("Approval", competitions.Search(User, SearchType.RecordForApproval));
        }
        #endregion

        #region /CompetitionArea/Editor/ConfirmApproval
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult ConfirmApproval(Guid id)
        {
            if (!User.IsApprover())
                return View(false);

            var competition = Provider.CompetitionRepository.SearchByPrimaryKey(id);

            if (competition == null || !competition.CanApprove(User))
                return RedirectHome;

            var competitionQuery = from comp in Provider.CompetitionRepository.Where(c => c.ApprovalGuid == competition.ApprovalGuid && c.IsApproved)
                                   select comp;

            Guid approvedCompetitionGuid;

            if (competitionQuery.Any())
            {
                var approvedCompetition = competitionQuery.Single();

                approvedCompetitionGuid = approvedCompetition.Pk;
                competition.Approve(approvedCompetition);

                Provider.SaveChanges();
            }
            else
            {
                competition.IsApproved = true;

                approvedCompetitionGuid = competition.Pk;
                Provider.SaveChanges();
            }

            var competitions = Provider.CompetitionRepository.Where(c => c.ApprovalGuid == competition.ApprovalGuid && !c.IsApproved);
            Provider.CompetitionRepository.RemoveAll(competitions);

            Provider.SaveChanges();

            return RedirectToAction("Index", "Details", new { id = approvedCompetitionGuid });
        }
        #endregion

        #region CompetitionArea/Editor/PendingApprovals
        [Authorize(Roles = "Admin, Superuser")]
        public ActionResult PendingApprovals()
        {
            var competitions = Provider.CompetitionRepository.Where(c => c.IsApproved == false);

            return View("Approval", competitions.Search(User, SearchType.PendingApprovals));
        }
        #endregion
    }
}
